#include "Date.h"
namespace sladhu {
bool Date::set_month(int m) {
  if(m < 1 || m > 12) return false;
  month_ = m;
}
bool Date::set_day(int d) {
  if( d < 0 || d > 31) return false;
  if( d > DaysOfCurrentMonth()) return false;
  day_ = d;
  return true;
}

// return week of current day, 0 stands for Sunday
int Date::week() {
  return CountWeek(year_, month_, day_);
}
void Date::NextMonth() {
  ++month_;
  if (13 == month_) {
    NextYear();
    month_ = 1;
  }
}
void Date::PreviousMonth() {
  --month_;
  if (0 == month_) {
    PreviousYear();
    month_ = 12;
  }
}
void Date::NextDay() {
  ++day_;
  if ( day_ > DaysOfCurrentMonth()) {
    NextMonth();
    day_ = 1;
  }
}
void Date::PreviousDay() {
  --day_;
  if ( 0 == day_) {
    PreviousMonth();
    day_ = DaysOfCurrentMonth();
  }
}
bool Date::operator > (const Date & date) {
  if (LARGE == Compare(date)) return true;
  return false;
}
bool Date::operator >= (const Date & date) {
  if (LESS == Compare(date)) return false;
  return true;
}

bool Date::operator < (const Date & date) {
  if (LESS == Compare(date)) return true;
  return false;
}

bool Date::operator <= (const Date & date) {
  if (LARGE == Compare(date)) return false;
  return true;
}

bool Date::operator == (const Date & date) {
  if (EQUAL == Compare(date)) return true;
  return false;
}

bool Date::operator != (const Date & date) {
  if (EQUAL == Compare(date)) return false;
  return true;
}

std::ostream& operator << (std::ostream & os, const Date & date) {
  std::cout << date.year()
            << '-'
            << std::setfill('0') << std::setw(2)
            << date.month()
            << '-'
            << date.day();
}
enum Date::CMP Date::Compare(const Date & date) {
  if (year_ > date.year_) return LARGE;
  if (year_ < date.year_) return LESS;
  if (month_ > date.month_) return LARGE;
  if (month_ < date.month_) return LESS;
  if (day_ > date.day_) return LARGE;
  if (day_ < date.day_) return LESS;
  return EQUAL;
}
int Date::DaysOfCurrentMonth() {
switch(month_)  
 {  
 case   1:  
 case   3:  
 case   5:  
 case   7:  
 case   8:  
 case   10:  
 case   12:   return 31;  //MaxDay是给GetDate调用的
 case   4:  
 case   6:  
 case   9:  
 case   11:   return 30;
 case   2:  
 if(IsLeapYear())   //2月份应该特殊对待
   return 29;
 else
   return 28;
}
}
/* use zeller formula:
 * w = (y + [y/4] + [c/4] - 2c + [13(m+1)/5] + d - 1) % 7
 * w = 0 stands for Sunday
 * c = centry -1, that is year/100
 * y = year % 100
 * m = month ( 3 ~ 14 )
 * d = day
 */ 
int Date::CountWeek(int yr, int m, int d) {
  if (m < 3) {
    --yr;
    m+=12;
  }
  int c = yr/100;
  int y = yr%100;
  int w = (y + y/4 + c/4 - 2*c + (13*(m+1))/5 + d - 1) % 7;
  return w < 0 ? w + 7 : w;
}
} // end sladhu namespace 
